package com.back.encrypt;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 对称加密算法，分组密码
 * Bouncy Castle 底层 API
 * JDK 标准接口
 * Hutool 等工具库
 */

public class Sm4Util {

    //1.====================
    // 128位（16字节）密钥，示例中使用十六进制字符串表示
    //byte[] key = Hex.decode("0123456789ABCDEFFEDCBA9876543210");
    // 初始化向量（IV），必须为16字节
    //byte[] iv = Hex.decode("00000000000000000000000000000000");
    //String plaintext = "Hello, SM4!";
    //byte[] encrypted = encrypt(key, iv, plaintext.getBytes());
    //System.out.println("加密结果（Hex）: " + Hex.toHexString(encrypted));
    //byte[] decrypted = decrypt(key, iv, encrypted);
    //System.out.println("解密结果: " + new String(decrypted));


    /**
     *
     * @param key 密钥
     * @param iv 初始化向量（IV）必须为16字节
     * @param plaintext 加密内容
     * @return
     * @throws Exception
     */
    public static byte[] encrypt_BouncyCastle(byte[] key, byte[] iv, byte[] plaintext) throws Exception {
        // 组合SM4算法引擎、CBC模式和PKCS7填充
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
        cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv)); // true 表示加密模式

        byte[] output = new byte[cipher.getOutputSize(plaintext.length)];
        int len = cipher.processBytes(plaintext, 0, plaintext.length, output, 0);
        cipher.doFinal(output, len); // 处理最后的数据块并应用填充

        return output;
    }

    /**
     *
     * @param key 密钥
     * @param iv 初始化向量（IV）必须为16字节
     * @param ciphertext 解密内容
     * @return
     * @throws Exception
     */
    public static byte[] decrypt_BouncyCastle(byte[] key, byte[] iv, byte[] ciphertext) throws Exception {
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
        cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv)); // false 表示解密模式

        byte[] output = new byte[cipher.getOutputSize(ciphertext.length)];
        int len = cipher.processBytes(ciphertext, 0, ciphertext.length, output, 0);
        len += cipher.doFinal(output, len); // 处理数据并移除填充

        // 返回解密后的数据，可能需要去除末尾的零字节（取决于填充方式）
        byte[] result = new byte[len];
        System.arraycopy(output, 0, result, 0, len);
        return result;
    }



    //2.====================
    //byte[] key = new byte[16];
    //new SecureRandom().nextBytes(key);
    //SecretKeySpec keySpec = new SecretKeySpec(key, "SM4");

    // 生成IV
    //byte[] iv = new byte[16];
    //new SecureRandom().nextBytes(iv);
    //IvParameterSpec ivSpec = new IvParameterSpec(iv);
    //String plainText = "Hello, JDK SM4!";

    public static byte[] encrypt_jdk(SecretKeySpec keySpec, IvParameterSpec ivSpec,String plaintext) throws Exception {
        Cipher cipher = null;
        cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(plaintext.getBytes());
        return encrypted;
    }

    public static byte[] decrypt_jdk(SecretKeySpec keySpec, IvParameterSpec ivSpec,String ciphertext) throws Exception {
        Cipher cipher = null;
        cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(ciphertext.getBytes());
        return decrypted;
    }


    //3.====================

    // 密钥和IV（需要为16字节）
    //String key = "abc1111111111333";
    //String iv = "iviviviviviviviv";

    public static String encrypt_hutool(String key,String iv,String text) throws Exception {
        SM4 sm4 = new SM4(Mode.CBC, Padding.ZeroPadding, key.getBytes(), iv.getBytes());
        // 加密（返回16进制字符串）
        return sm4.encryptHex(text);
    }

    public static String decrypt_hutool(String key,String iv,String text) throws Exception {
        SM4 sm4 = new SM4(Mode.CBC, Padding.ZeroPadding, key.getBytes(), iv.getBytes());
        return sm4.decryptStr(text, CharsetUtil.CHARSET_UTF_8);
    }





}
